package hasthi.tools;

import static hasthi.common.HasthiOptions.*;
import hasthi.common.BaseContext;
import hasthi.common.HasthiException;
import hasthi.common.Utils;
import hasthi.common.HasthiException.FaultCode;
import hasthi.common.constants.HasthiConstants;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.globus.gsi.GlobusCredential;
import org.globus.gsi.gssapi.GlobusGSSCredentialImpl;
import org.globus.myproxy.MyProxy;
import org.globus.myproxy.MyProxyException;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;

public class ProxyRenewer {

    private static Log log = LogFactory.getLog(HasthiConstants.LOGGER_NAME);

    private final String username;
    private final String password;
    private final int port;
    private final int lifetime;
    private final String hostname;

    private GSSCredential credential;

    public ProxyRenewer(final String username, final String password, final int port,
            final int lifetime, final String hostname) {
        super();
        this.username = username;
        this.password = password;
        this.port = port;
        this.lifetime = lifetime;
        this.hostname = hostname;
    }

    public ProxyRenewer(String username, String password, int lifetime) {
        super();
        this.username = username;
        this.password = password;
        this.lifetime = lifetime;
        hostname = "rainier.extreme.indiana.edu";
        this.port = MyProxy.DEFAULT_PORT;
    }

    public ProxyRenewer(BaseContext baseContext) throws HasthiException {
        Properties properties = baseContext.getProperties();
        this.username = Utils.getStringProperty(properties, MYPROXY_USERNAME, null);
        this.password = Utils.getStringProperty(properties, MYPROXY_PASSWD, null);
        this.lifetime = Utils.getIntProperty(properties, MYPROXY_LIFETIME, 14400);
        hostname = Utils.getStringProperty(properties, MYPROXY_SERVER,
                "rainier.extreme.indiana.edu");
        this.port = Utils.getIntProperty(properties, MYPROXY_PORT, MyProxy.DEFAULT_PORT);

        if (username == null || password == null) {
            throw new HasthiException("Myproxy username or password must be specified",
                    FaultCode.ConfigError);
        }
    }

    public GSSCredential getCredentail() throws HasthiException {
        try {
            if (credential == null || credential.getRemainingLifetime() < 60 * 10) {
                credential = renewProxy();
            }
            return credential;
        } catch (GSSException e) {
            throw new HasthiException(e, FaultCode.ErrorAtDependentService);
        }
    }

    private GSSCredential renewProxy() throws HasthiException {

        try {
            String proxyloc = null;
            MyProxy myproxy = new MyProxy(hostname, port);
            GSSCredential proxy = myproxy.get(username, password, lifetime);

            // System.out.println("GFAC Proxy:" + proxy.toString());

            GlobusCredential globusCred = null;
            if (proxy instanceof GlobusGSSCredentialImpl) {
                globusCred = ((GlobusGSSCredentialImpl) proxy).getGlobusCredential();
                log.info("got proxy from myproxy for " + username + " with " + lifetime
                        + " lifetime.");
                // InputStream is = Runtime.getRuntime().exec(
                // "/bin/env").getInputStream();
                // BufferedReader in
                // = new BufferedReader(new InputStreamReader(is));
                // String str;
                // while((str = in.readLine()) != null) {
                // if(str.startsWith("X509_USER_PROXY=")) {
                // proxyloc = str.substring("X509_USER_PROXY=".length());
                // }
                // }
                // // proxyloc = XpolaUtil.getSysEnv("X509_USER_PROXY");
                // log.info("proxy location0: " + proxyloc);
                String uid = username;
                if (proxyloc == null) {
                    // uid = XpolaUtil.getSysUserid();
                    log.info("uid: " + uid);
                    proxyloc = "/tmp/x509up_u" + uid;
                }
                log.info("proxy location: " + proxyloc);
                File proxyfile = new File(proxyloc);
                if (proxyfile.exists() == false) {
                    String dirpath = proxyloc.substring(0, proxyloc.lastIndexOf('/'));
                    File dir = new File(dirpath);
                    if (dir.exists() == false) {
                        dir.mkdirs();
                        log.info("new directory " + dirpath + " is created.");
                    }
                    proxyfile.createNewFile();
                    log.info("new proxy file " + proxyloc + " is created.");
                }
                FileOutputStream fout = new FileOutputStream(proxyfile);
                globusCred.save(fout);
                fout.close();
                Runtime.getRuntime().exec("/bin/chmod 600 " + proxyloc);
                log.info("proxy file renewed");

                System.out.println("Proxy file renewed to " + proxyloc + " for the user "
                        + username + " with " + lifetime + " lifetime.");

            }
            return proxy;
        } catch (MyProxyException e) {
            throw new HasthiException(e, FaultCode.ErrorAtDependentService);
        } catch (FileNotFoundException e) {
            throw new HasthiException(e, FaultCode.LocalError);
        } catch (IOException e) {
            throw new HasthiException(e, FaultCode.LocalError);
        }
    }

}
